/*
 * PhotonRTOS础光实时操作系统 -- 多核调度
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Jiayuan Liang <liangjiayuan@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#include <photon/cpumask.h>
#include <photon/smp.h>

static void (*smp_ioc_cb)(void);

void smp_set_ioc_isr(void (*fn)(void))
{
	smp_ioc_cb = fn;
}

void smp_call_ioc_isr(void)
{
	if (smp_ioc_cb != NULL) {
		smp_ioc_cb();
	}
}

static void cpu_send_async_request(uint32_t cpu)
{
		if (cpu == 0) {
        IfxSrc_setRequest(&SRC_GPSR_GPSR0_SR0);
    } else if (cpu == 1) {
        IfxSrc_setRequest(&SRC_GPSR_GPSR0_SR1);
    }
}

static void cpu_send_shutdown_request(uint32_t cpu)
{
	if (cpu == 0) {
		IfxSrc_setRequest(&SRC_GPSR_GPSR0_SR2);
	}else if (cpu == 1) {
		IfxSrc_setRequest(&SRC_GPSR_GPSR0_SR3);
	}
}

static void cpu_send_ioc_request(uint32_t cpu)
{
	if (cpu == 0) {
		IfxSrc_setRequest(&SRC_GPSR_GPSR0_SR4);
	}else if (cpu == 1) {
		IfxSrc_setRequest(&SRC_GPSR_GPSR0_SR5);
	}
}

static send_cpu_ipi(int32_t cpu, enum ipi_cmd_type cmd_type)
{
	switch (cmd_type) {
	case IPI_SHUTDOWN:
		cpu_send_shutdown_request(cpu);
		break;
	case IPI_IOC:
		cpu_send_ioc_request(cpu);
		break;
	case IPI_ASYNC:
		cpu_send_async_request(cpu);
		break;
	default:
		pr_err("unknown IPI type %d\n", cmd_type);
		break;
	}
}


/**
 * 触发IPI中断
 */
void arch_raise_ipi(const struct cpumask *mask, enum ipi_cmd_type cmd_type)
{
    int32_t cpu;
    int32_t mycpu;

    mycpu = smp_processor_id();

	/**
	 * 先发送给非当前CPU
	 */
	for_each_cpu(cpu, mask) {
		if (cpu != mycpu) {
			send_cpu_ipi(cpu, cmd_type);
		}
    }

	/**
	 * 最后发送给当前CPU，避免自己先进入关机。
	 */
	for_each_cpu(cpu, mask) {
		if (cpu == mycpu) {
			send_cpu_ipi(cpu, cmd_type);
		}
	}
}
